<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.4.0 / SVN信息: $Id: class.JCAT_String.php 1490 2009-03-19 12:38:51Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/




/**
 * What's this Class ?
 *
 * @author		alee
 * @access		public
 */
class JCAT_String
{
	
	const NL_LOCAL = 0 ;
	const NL_WIN = 1 ;
	const NL_LINUX = 2 ;
	const NL_MAC = 3 ;


	/**
	 * 截取函数
	 * 
	 * @access	public
	 * @param	$sIn					string	传入字符
	 * @param	$nCharLength		int		截取的字符长度
	 * @param	$sReplaceStr='..'	string	替换字串
	 * @static
	 * @return	string
	 */
	static public function Deflate( $sIn, $nCharLength, $sReplaceStr='..' ) 
	{
		if( $nCharLength<0 )
		{
			return $sIn;
		}
		
		// 多字节 字长
		$nMultiByteLen = strtolower(JCAT::$CHARSET_PROJECT)==='utf-8' ? 3: 2 ;
		
		$sReturn = '' ;
		$nCharFixedLength = 0 ;
		$nInByteLength=strlen($sIn);
		for($nByteIdx=0;$nByteIdx<$nInByteLength;)
		{
			if( $nCharFixedLength++>=$nCharLength )
			{
				break ;
			}
			
			$nCharLen = ord(substr($sIn,$nByteIdx,1))>127? $nMultiByteLen: 1 ;
			$sReturn.= substr($sIn,$nByteIdx,$nCharLen) ;
			$nByteIdx+= $nCharLen ;
		}
		
		// 
		if( $nByteIdx<$nInByteLength-1 )
		{
			$sReturn.= $sReplaceStr ;
		}
		
		return $sReturn ;
	}

	/**
	 * 字符串编码
	 * 
	 * @access	public
	 * @param	$sIn		string	What's this Parameter ?
	 * @static
	 * @return	string
	 */
	static public function Encode( $sIn, $nByteLenPerLine=0 ) 
	{
		$sRet = base64_encode(urlencode($sIn)) ;
		$sRet = str_replace('=','!',$sRet) ;
		$sRet = str_replace('+','_',$sRet) ;
		
		// 整理 块状 格式
		if($nByteLenPerLine>0)
		{
			$sRet = chunk_split($sRet,$nByteLenPerLine,"\r\n") ;
			
			// 清除末尾的 \r\n
			$sRet = preg_replace("/\r\n$/",'',$sRet) ;
		}
		
		// 返回
		return $sRet ;
	}

	/**
	 * 字符串解码
	 * 
	 * @access	public
	 * @param	$sIn		string	What's this Parameter ?
	 * @static
	 * @return	string
	 */
	static public function Decode( $sIn ) 
	{
		// 清除 块状 格式
		$sRet = str_replace("\r",'',$sIn) ;
		$sRet = str_replace("\n",'',$sRet) ;
		
		$sRet = str_replace('!','=',$sRet) ;
		$sRet = str_replace('_','+',$sRet) ;
		
		return urldecode(base64_decode($sRet)) ;
	}
	
	/**
	 * 将日期格式转换为 时间戳
	 *
	 * @access	public
	 * @param	$sDate			string
	 * @static
	 * @return	int
	 */
	static public function DateToTimeStamp($sDate)
	{
		$arrResult = array() ;
		if( preg_match('/^(\d{2}|\d{4})[\/\-\.](\d{1,2})[\/\-\.](\d{1,2})( (\d{1,2}):(\d{1,2})(:(\d{1,2}))?)?$/',$sDate,$arrResult) )
		{
			$nYear = intval($arrResult[1]) ;
			$nMonth = intval($arrResult[2]) ;
			$nDay = intval($arrResult[3]) ;
			$nHour = intval(@$arrResult[5]) ;
			$nMinute = intval(@$arrResult[6]) ;
			$nSec = intval(@$arrResult[8]) ;
			
			if( $nYear<100 )
			{
				$nYear+= 2000 ;
			}
			
			return mktime($nHour,$nMinute,$nSec,$nMonth,$nDay,$nYear) ;
		}
		
		else
		{
			return 0 ;
		}
	}
	
	
	/**
	 * 格式化显示 空值
	 *
	 * @access	public
	 * @param	$Value			mixed
	 * @param	$sShow='--'	string
	 * @static
	 * @return	string
	 */
	static public function FormatNull($Value,$sShow='--')
	{
		return empty($Value)? $sShow: $Value ;
	}


	/**
	 * 转换换行风格
	 *
	 * @access	public
	 * @param	$sInString		string
	 * @static
	 * @return	string
	 */
	static public function ConvertNewlineStyle($sInString,$nStyle=self::NL_LOCAL)
	{
		$sOutString = str_replace("\r\n","\n",$sInString) ;
		$sOutString = str_replace("\r","\n",$sOutString) ;

		switch ($nStyle)
		{
			case self::NL_LOCAL :
				return JCAT_OS::IsLinux()? $sOutString: str_replace("\n",JCAT_OS::GetNewline(),$sOutString) ;
				break ;
				
			case self::NL_WIN :
				return str_replace("\n","\r\n",$sOutString) ;
				break ;
				
			case self::NL_LINUX :
				return $sOutString ;
				break ;
				
			case self::NL_MAC :
				return str_replace("\n","\r",$sOutString) ;
				break ;
				
			default :
				JCAT_ASSERT::ASSERT_(0,JCAT_Language::SentenceEx('无效的参数：$nStyle=%s','JCAT',null,$nStyle)) ;
				return $sInString ;
				break ;
		}
	}

	/**
	 * 构造函数
	 *
	 * @access	public
	 * @param	$sSourceString		string
	 * @return	void
	 */
	public function JCAT_String($sSourceString)
	{
		$this->sSourceString = $sSourceString ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetSource()
	{
		return $this->sSourceString ;
	}
	
	/**
	 * 重载运算符
	 *
	 * @access	public
	 * @return	string
	 */
	public function __toString()
	{
		return $this->sSourceString ;		
	}
	
	/**
	 * 序列化
	 *
	 * @access	public
	 * @return	array
	 */
	public function __sleep()
	{
		return array( JCAT_Package::MakePrivatePropertyNameForSerialize('sSourceString',__CLASS__) ) ;
	}
	
	/**
	 * 使用一个PHP原生函数处理 对象中的字符串资源，并返回结果。
	 * 这用这个对象方法，你可以不必通过 GetSouce() 取回全部的字符串资源。
	 *
	 * @access	public
	 * @return	mixed
	 */
	public function __call($sAccessFuncName,$arrArgs)
	{
		$sFuncName = strtolower($sAccessFuncName) ;
		$sFuncName = str_replace('_','',$sFuncName) ;
		
		if(!isset(self::$arrStringProcessFunctions[$sFuncName]))
		{
			$sFuncName = 'str'.$sFuncName ;
			if(!isset(self::$arrStringProcessFunctions[$sFuncName]))
			{
				throw new JCAT_Exception(JCAT_Language::SentenceEx(
					'正在访问一个未知的字符串处理函数：%s'
					, 'JCAT', null
					, $sAccessFuncName
				)) ;
			}
		}
		
		// 整理参数表
		array_splice($arrArgs,self::$arrStringProcessFunctions[$sFuncName]['pos'],$this->sSourceString) ;
		
		// 处理返回
		return call_user_func_array(self::$arrStringProcessFunctions[$sFuncName],$arrArgs) ;
	}
	
	/**
	 * 创建一个片段迭代器
	 *
	 * @access	public
	 * @param	$sSeparator				string
	 * @param	$bUseRegExp=false		bool			是否使用正则表达式来切片
	 * @return	JACT_IIterator
	 */
	public function CreateSliceIterator($sSeparator,$bUseRegExp=false)
	{
		return new JCAT_ArrayIterator(( $bUseRegExp? 
					explode($sSeparator,$this->sSourceString) :
					preg_split($sSeparator,$this->sSourceString)
			)) ;
	}
	
	/**
	 * 使用一个PHP原生函数处理 对象中的字符串资源，并返回结果。
	 * 这用这个对象方法，你可以不必通过 GetSouce() 取回全部的字符串资源。
	 * 第一个参数是处理函数，后面可以跟随传递给 处理函数的参数，使用 JCAT_String::_THIS 常量表示字符串自身。
	 * 如果没有出现 JCAT_String::_THIS， 字符串资源 会做为最后一项参数传递给 处理函数
	 *
	 * @access	public
	 * @param	$Function		callback
	 * @return	mixed
	 */
	public function Process($Function/* $aParameter....*/)
	{
		if( !is_callable($Function,false) )
		{
			throw new JCAT_Exception(JCAT_Language::SentenceEx(
				'正在使用无效的 $Function 参数: %s'
				, 'JCAT', null
				, $Function
			)) ;
		}
		
		$arrArgs = func_get_args() ;
		array_shift($arrArgs) ;
		
		$bInput = false ;
		foreach ($arrArgs as $nIdx=>$Value)
		{
			if( self::_THIS===$Value )
			{
				$arrArgs[$nIdx] = $this->sSourceString ;
				$bInput = true ;
				break ;
			}
		}
		
		if(!$bInput)
		{
			$arrArgs[] = $this->sSourceString ;
		}
		
		return call_user_func_array($Function,$arrArgs) ;
	}
	
	const _THIS = '~!%^)#*@_+*($($%' ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		string
	 */
	private $sSourceString ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @static
	 * @var		array
	 */
	static private $arrStringProcessFunctions = array(
				'addcslashes' => array( 'function'=>'addcslashes', 'pos'=>0 ) 
				, 'addslashes' => array( 'function'=>'addslashes', 'pos'=>0 ) 
				, 'bin2hex' => array( 'function'=>'bin2hex', 'pos'=>0 ) 
				, 'chr' => array( 'function'=>'chr', 'pos'=>0 ) 
				, 'chunksplit' => array( 'function'=>'chunk_split', 'pos'=>0 ) 
				, 'convertcyrstring' => array( 'function'=>'convert_cyr_string', 'pos'=>0 ) 
				, 'convertuudecode' => array( 'function'=>'convert_uudecode', 'pos'=>0 ) 
				, 'convertuuencode' => array( 'function'=>'convert_uuencode', 'pos'=>0 ) 
				, 'countchars' => array( 'function'=>'count_chars', 'pos'=>0 ) 
				, 'crc32' => array( 'function'=>'crc32', 'pos'=>0 ) 
				, 'crypt' => array( 'function'=>'crypt', 'pos'=>0 ) 
				, 'explode' => array( 'function'=>'explode', 'pos'=>0 ) 
				, 'hebrev' => array( 'function'=>'hebrev', 'pos'=>0 ) 
				, 'hebrevc' => array( 'function'=>'hebrevc', 'pos'=>0 ) 
				, 'htmlentitydecode' => array( 'function'=>'html_entity_decode', 'pos'=>0 ) 
				, 'htmlentities' => array( 'function'=>'htmlentities', 'pos'=>0 ) 
				, 'htmlspecialcharsdecode' => array( 'function'=>'htmlspecialchars_decode', 'pos'=>0 ) 
				, 'htmlspecialchars' => array( 'function'=>'htmlspecialchars', 'pos'=>0 ) 
				, 'implode' => array( 'function'=>'implode', 'pos'=>0 ) 
				, 'levenshtein' => array( 'function'=>'levenshtein', 'pos'=>0 ) 
				, 'ltrim' => array( 'function'=>'ltrim', 'pos'=>0 ) 
				, 'md5' => array( 'function'=>'md5', 'pos'=>0 ) 
				, 'metaphone' => array( 'function'=>'metaphone', 'pos'=>0 ) 
				, 'nl2br' => array( 'function'=>'nl2br', 'pos'=>0 ) 
				, 'ord' => array( 'function'=>'ord', 'pos'=>0 ) 
				, 'parsestr' => array( 'function'=>'parse_str', 'pos'=>0 ) 
				, 'quotedprintabledecode' => array( 'function'=>'quoted_printable_decode', 'pos'=>0 ) 
				, 'quotemeta' => array( 'function'=>'quotemeta', 'pos'=>0 ) 
				, 'rtrim' => array( 'function'=>'rtrim', 'pos'=>0 ) 
				, 'sha1' => array( 'function'=>'sha1', 'pos'=>0 ) 
				, 'similartext' => array( 'function'=>'similar_text', 'pos'=>0 ) 
				, 'soundex' => array( 'function'=>'soundex', 'pos'=>0 ) 
				, 'sscanf' => array( 'function'=>'sscanf', 'pos'=>0 ) 
				, 'strgetcsv' => array( 'function'=>'str_getcsv', 'pos'=>0 ) 
				, 'strireplace' => array( 'function'=>'str_ireplace', 'pos'=>0 ) 
				, 'strpad' => array( 'function'=>'str_pad', 'pos'=>0 ) 
				, 'strreplace' => array( 'function'=>'str_replace', 'pos'=>0 ) 
				, 'strrot13' => array( 'function'=>'str_rot13', 'pos'=>0 ) 
				, 'strshuffle' => array( 'function'=>'str_shuffle', 'pos'=>0 ) 
				, 'strsplit' => array( 'function'=>'str_split', 'pos'=>0 ) 
				, 'strwordcount' => array( 'function'=>'str_word_count', 'pos'=>0 ) 
				, 'strcasecmp' => array( 'function'=>'strcasecmp', 'pos'=>0 ) 
				, 'strchr' => array( 'function'=>'strchr', 'pos'=>0 ) 
				, 'strcmp' => array( 'function'=>'strcmp', 'pos'=>0 ) 
				, 'strcoll' => array( 'function'=>'strcoll', 'pos'=>0 ) 
				, 'strcspn' => array( 'function'=>'strcspn', 'pos'=>0 ) 
				, 'striptags' => array( 'function'=>'strip_tags', 'pos'=>0 ) 
				, 'stripcslashes' => array( 'function'=>'stripcslashes', 'pos'=>0 ) 
				, 'stripos' => array( 'function'=>'stripos', 'pos'=>0 ) 
				, 'stripslashes' => array( 'function'=>'stripslashes', 'pos'=>0 ) 
				, 'stristr' => array( 'function'=>'stristr', 'pos'=>0 ) 
				, 'strlen' => array( 'function'=>'strlen', 'pos'=>0 ) 
				, 'strnatcasecmp' => array( 'function'=>'strnatcasecmp', 'pos'=>0 ) 
				, 'strnatcmp' => array( 'function'=>'strnatcmp', 'pos'=>0 ) 
				, 'strncasecmp' => array( 'function'=>'strncasecmp', 'pos'=>0 ) 
				, 'strncmp' => array( 'function'=>'strncmp', 'pos'=>0 ) 
				, 'strpbrk' => array( 'function'=>'strpbrk', 'pos'=>0 ) 
				, 'strpos' => array( 'function'=>'strpos', 'pos'=>0 ) 
				, 'strrchr' => array( 'function'=>'strrchr', 'pos'=>0 ) 
				, 'strrev' => array( 'function'=>'strrev', 'pos'=>0 ) 
				, 'strripos' => array( 'function'=>'strripos', 'pos'=>0 ) 
				, 'strrpos' => array( 'function'=>'strrpos', 'pos'=>0 ) 
				, 'strspn' => array( 'function'=>'strspn', 'pos'=>0 ) 
				, 'strstr' => array( 'function'=>'strstr', 'pos'=>0 ) 
				, 'strtok' => array( 'function'=>'strtok', 'pos'=>0 ) 
				, 'strtolower' => array( 'function'=>'strtolower', 'pos'=>0 ) 
				, 'strtoupper' => array( 'function'=>'strtoupper', 'pos'=>0 ) 
				, 'strtr' => array( 'function'=>'strtr', 'pos'=>0 ) 
				, 'substrcompare' => array( 'function'=>'substr_compare', 'pos'=>0 ) 
				, 'substrcount' => array( 'function'=>'substr_count', 'pos'=>0 ) 
				, 'substrreplace' => array( 'function'=>'substr_replace', 'pos'=>0 ) 
				, 'substr' => array( 'function'=>'substr', 'pos'=>0 ) 
				, 'trim' => array( 'function'=>'trim', 'pos'=>0 ) 
				, 'ucfirst' => array( 'function'=>'ucfirst', 'pos'=>0 ) 
				, 'ucwords' => array( 'function'=>'ucwords', 'pos'=>0 ) 
				, 'wordwrap' => array( 'function'=>'wordwrap', 'pos'=>0 ) 
	 ) ;
}
?>